Skip to content

Audit: resilience fixes, dead-code cleanup, and dependency overhaul - #46

Merged
brah merged 3 commits into
mainfrom
audit/resilience-fixes
Jun 16, 2026
Merged

Audit: resilience fixes, dead-code cleanup, and dependency overhaul#46
brah merged 3 commits into
mainfrom
audit/resilience-fixes

Conversation

@brah

@brah brah commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Outcome of a code-quality audit of the bot. Three logically-scoped commits; each is self-consistent and compiles independently.

1. Resilience & lifecycle fixes (a9fdf33)

  • Cache deadlock: MediaCache.update_cache held the non-reentrant cache_lock and re-acquired it via save_cache_to_disk → latent hang on every post-TTL refresh. Split out a lock-free _write_items_to_disk the lock holder calls directly.
  • Startup model: moved one-time init out of on_ready (fires on every gateway reconnect → leaked aiohttp sessions + re-crawled the cache) into setup_hook. PlexBot.close() now stops the gateway before closing the shared Tautulli/TMDB sessions so background tasks can't use (or silently re-open) a closed session.
  • Event loop: the git fetch version check no longer blocks the loop — it runs once at startup via asyncio.gather(asyncio.to_thread(...)), and the "unknown" failure sentinel is no longer read as "outdated".
  • Shared-session ownership: cogs no longer close the shared session in cog_unload (the bot owns it); ServerCommands cancels its presence task instead.
  • Response handling: plex_data/recommendations route Tautulli responses through check_response/get_response_data (no more crashes when the API returns None), guard a null data payload, and use stdlib zoneinfo instead of pytz.

2. Dead code + linting/CI (58d7cb9)

  • Removed the unused utilities.Config class and MyEmbedDescriptionPageSource, plus dead imports across the package.
  • Added a conservative ruff config (F, E9) and a CI workflow (ruff + compileall smoke test); bumped the black/ruff target to py312.

3. Dependencies + docs (c6d8afd)

  • requirements.txt: declare only directly-imported deps — add aiohttp/matplotlib (were only transitive), drop unused requests/numpy and the bogus datetime PyPI package, pin everything to current stable, and add tzdata so zoneinfo has an IANA database on platforms without a system copy.
  • Documented the real Python floor (3.12, required by nextcord 3.x).

Notes

  • Verified green locally: ruff check . + compileall.
  • Two behaviors worth a manual smoke-test post-merge: the plex chart … commands (pandas 3.0 + zoneinfo path) and plex downloading (qBittorrent client bump).
  • Deliberately not included here: removing the dead TMDB integration, persisting the cache last_updated timestamp, and consolidating the duplicated duration formatters — flagged as follow-ups.

🤖 Generated with Claude Code

brah and others added 3 commits June 16, 2026 15:13
- media_cache: fix a self-deadlock where update_cache held the non-reentrant
  cache_lock and then re-acquired it via save_cache_to_disk. Split out a
  lock-free _write_items_to_disk that the lock holder calls directly.
- plexbot: move one-time init out of on_ready (which fires on every gateway
  reconnect, leaking sessions and re-crawling the cache) into setup_hook.
  Centralize session teardown in PlexBot.close(), which now stops the gateway
  before closing the shared Tautulli/TMDB sessions so background tasks can't
  use (or silently re-open) a closed session.
- server_commands: run the git version check off the event loop via
  asyncio.gather(asyncio.to_thread(...)), once at startup; cancel the presence
  task on unload instead of closing the shared session; don't treat the
  "unknown" git sentinel as an outdated version.
- media_commands: stop closing the shared Tautulli/TMDB session in cog_unload
  (the bot owns it now).
- plex_data/recommendations: route Tautulli responses through
  check_response/get_response_data, guard against a null "data" payload, and
  use stdlib zoneinfo instead of pytz.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Delete the unused utilities.Config class and MyEmbedDescriptionPageSource,
  and drop unused imports across the package (all caught by ruff F401).
- Add a conservative ruff config (F, E9) plus a CI workflow that runs ruff and
  a compileall smoke test; bump the black/ruff target to py312.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- requirements.txt: declare only directly-imported deps. Add aiohttp and
  matplotlib (previously only transitive), drop the unused requests/numpy and
  the bogus "datetime" PyPI package, pin everything to current stable, and add
  tzdata so stdlib zoneinfo has an IANA database on platforms without a system
  copy (Windows, slim containers).
- Document the real Python floor (3.12, required by nextcord 3.x).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant